import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

class WavFileParser {
  final File file;

  late int sampleRate;
  late int bitDepth;
  late int channels;
  late List<double> amplitudes; // 归一化振幅值(-1.0到1.0)

  WavFileParser(this.file);

  Future<void> parse() async {
    final bytes = await file.readAsBytes();
    final byteData = ByteData.view(bytes.buffer);
    int offset = 0;

    // 验证WAV文件标识
    if (String.fromCharCodes(byteData.buffer.asUint8List(offset, 4)) != 'RIFF') {
      throw FormatException('不是有效的WAV文件');
    }
    offset += 4;

    // 跳过文件大小信息
    offset += 4;

    // 验证WAVE标识
    if (String.fromCharCodes(byteData.buffer.asUint8List(offset, 4)) != 'WAVE') {
      throw FormatException('不是有效的WAV文件');
    }
    offset += 4;

    // 解析fmt块
    while (offset < bytes.length) {
      final chunkId = String.fromCharCodes(byteData.buffer.asUint8List(offset, 4));
      offset += 4;
      final chunkSize = byteData.getUint32(offset, Endian.little);
      offset += 4;

      if (chunkId == 'fmt ') {
        // 验证PCM格式
        final audioFormat = byteData.getUint16(offset, Endian.little);
        if (audioFormat != 1) {
          throw FormatException('仅支持PCM编码的WAV文件');
        }
        offset += 2;

        // 解析声道数
        channels = byteData.getUint16(offset, Endian.little);
        offset += 2;

        // 解析采样率
        sampleRate = byteData.getUint32(offset, Endian.little);
        offset += 4;

        // 跳过字节率和块对齐
        offset += 6;

        // 解析位深
        bitDepth = byteData.getUint16(offset, Endian.little);
        offset += 2;

        // 跳过剩余的fmt块数据
        offset += chunkSize - 16;
        break;
      } else {
        // 跳过其他块
        offset += chunkSize;
      }
    }

    // 解析data块
    while (offset < bytes.length) {
      final chunkId = String.fromCharCodes(byteData.buffer.asUint8List(offset, 4));
      offset += 4;
      final chunkSize = byteData.getUint32(offset, Endian.little);
      offset += 4;

      if (chunkId == 'data') {
        // 提取振幅数据
        amplitudes = _extractAmplitudes(byteData, offset, chunkSize);
        break;
      } else {
        // 跳过其他块
        offset += chunkSize;
      }
    }

    if (amplitudes.isEmpty) {
      throw FormatException('未找到音频数据');
    }
  }

  // 提取振幅数据并归一化
  List<double> _extractAmplitudes(ByteData byteData, int offset, int chunkSize) {
    final amplitudes = <double>[];
    final bytesPerSample = bitDepth ~/ 8;
    final totalSamples = chunkSize ~/ bytesPerSample;

    // 对于立体声，我们只取左声道或取平均值
    for (int i = 0; i < totalSamples; i += channels) {
      double sample;

      switch (bitDepth) {
        case 8:
        // 8位是无符号整数
          sample = (byteData.getUint8(offset) - 128) / 128.0;
          offset += 1;
          break;
        case 16:
        // 16位是有符号整数（小端）
          sample = byteData.getInt16(offset, Endian.little) / 32768.0;
          offset += 2;
          break;
        case 32:
        // 32位是有符号整数（小端）
          sample = byteData.getInt32(offset, Endian.little) / 2147483648.0;
          offset += 4;
          break;
        default:
          throw FormatException('不支持的位深: $bitDepth');
      }

      amplitudes.add(sample);

      // 跳过其他声道
      offset += bytesPerSample * (channels - 1);
    }

    return amplitudes;
  }

  // 降采样处理，优化绘制性能
  List<double> downSample(int targetPoints) {
    if (amplitudes.length <= targetPoints) return amplitudes;

    final step = amplitudes.length / targetPoints;
    final result = <double>[];

    for (int i = 0; i < targetPoints; i++) {
      final index = (i * step).round().clamp(0, amplitudes.length - 1);
      result.add(amplitudes[index]);
    }

    return result;
  }
}